﻿using DeHeng_Mes.Model.PlcModel.Left;
using System;
using System.Collections.Generic;
using DeHeng_Mes.Model.PlcModel.Right;
using DeHeng_Mes.Constant;
using S7.Net;
using System.Management;
using DeHeng_Mes.Model;
using DeHeng_Mes.Model.Table;
using DeHeng_Mes.Model.PlcModel.Front;
using DeHeng_Mes.Model.PlcModel.Sub;

namespace DeHeng_Mes.Utils
{
    public static class MappingTable
    {
        /// <summary>
        /// plc数据与实体类的映射
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static Dictionary<object, Type> PlcMapping(Plc plc, string plcName)
        {
            // 初始化返回值
            Dictionary<object, Type> dic = new Dictionary<object, Type>();

            // 定义一个类型和地址的映射表
            var typeAddressMap = new Dictionary<string, List<(Type type, int address)>>
            {
                { "front", new List<(Type, int)>
                    {
                        (typeof(FrontBeat), SystemConstant.DB6001),
                        (typeof(FrontCode), SystemConstant.DB6009),
                        (typeof(FrontDeviceErrorMessage), SystemConstant.DB6006),
                        (typeof(FrontDeviceErrorStatus), SystemConstant.DB6010),
                        (typeof(FrontPower), SystemConstant.DB6003),
                        (typeof(FrontProduceOperation), SystemConstant.DB6004),
                        (typeof(FrontStationError), SystemConstant.DB6002),
                        (typeof(FrontStationStatus), SystemConstant.DB6000),
                        (typeof(FrontCollection), SystemConstant.DB6007),
                        (typeof(FrontProduceOrder), SystemConstant.DB6012),
                        (typeof(FrontProduceStatus), SystemConstant.DB6013),
                        //(typeof(FrontIssuedCode), SystemConstant.DB6014),
                        (typeof(FrontGlueCode), 6020),
                        (typeof(FrontGlueStatusToMes), 6021),
                    }
                },
                { "sub", new List<(Type, int)>
                    {
                        (typeof(SubBeat), SystemConstant.DB6001),
                        (typeof(SubCode), SystemConstant.DB6009),
                        (typeof(SubDeviceErrorMessage), SystemConstant.DB6006),
                        (typeof(SubDeviceErrorStatus), SystemConstant.DB6010),
                        (typeof(SubPower), SystemConstant.DB6003),
                        (typeof(SubProduceOperation), SystemConstant.DB6004),
                        (typeof(SubStationError), SystemConstant.DB6002),
                        (typeof(SubStationStatus), SystemConstant.DB6000),
                        (typeof(SubCollection), SystemConstant.DB6007),
                        (typeof(SubProduceOrder), SystemConstant.DB6012),
                        (typeof(SubProduceStatus), SystemConstant.DB6013),
                        (typeof(SubGlueCode), 6020),
                        (typeof(SubGlueStatusToMes), 6021),
                    }
                }
            };

            // 定义读取数据并添加到字典的方法
            void AddInstance(Type type, int address)
            {
                // 引用ReadClass方法的命名空间和类
                var method = typeof(Plc).GetMethod("ReadClass", new Type[] { typeof(int), typeof(int) })?.MakeGenericMethod(type);
                var instance = method.Invoke(plc, new object[] { address, 0 });
                dic.Add(instance, type);
            }

            try
            {
                // 检查并处理对应的Name类型
                if (typeAddressMap.ContainsKey(plcName))
                {
                    foreach (var (type, address) in typeAddressMap[plcName])
                    {
                        AddInstance(type, address);
                    }
                }

                return dic;
            }
            catch (Exception ex)
            {
                Tools.ProduceLogTextError($"{plcName}获取Plc数据实例与实例类型映射失败，原因是：" + ex.Message);
            }

            return dic;
        }


        /// <summary>
        /// 偏移量映射表
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static (int, int) GetOff(string name)
        {
            Dictionary<string, Dictionary<int, int>> dic = new Dictionary<string, Dictionary<int, int>>();
            int count = 0;
            int outerKey = 0;
            int innerValue = 0;
            string key = "";
            if (name.Contains("ErrorStatus"))
            {
                //处理报警信息
                count = 40;
                outerKey = 0;
                innerValue = 0;
                key = "ErrorStatus";
            }

            // 初始化映射表
            for (int i = 1; i <= count; i++)
            {
                string keys = key + i; // 生成键名
                Dictionary<int, int> innerDic = new Dictionary<int, int>
                {
                    { outerKey, innerValue } // 添加初始值
                };

                // 将innerDic添加到dic
                dic[keys] = innerDic;

                // 递增内层字典的值
                innerValue++;

                // 检查是否需要更新outerKey和重置innerValue
                if (innerValue == 8)
                {
                    innerValue = 0; // 重置为0
                    outerKey++; // 增加outerKey
                }
            }

            //获取对应数据
            foreach (var item in dic)
            {
                if (name.Equals(item.Key))
                {
                    foreach (var item1 in item.Value)
                    {
                        return (item1.Key, item1.Value);
                    }
                }
            }
            return (10, 10);
        }

        /// <summary>
        /// 获取Cpu唯一标识
        /// </summary>
        public static string DeviceIdentifier()
        {
            string cpuId = string.Empty;
            using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("select ProcessorId from Win32_Processor"))
            {
                foreach (ManagementObject obj in searcher.Get())
                {
                    cpuId = obj["ProcessorId"].ToString();
                    break;
                }
            }
            return cpuId;
        }

        /// <summary>
        /// 设备与数据库账号映射表
        /// </summary>
        /// <param name="cpuIp"></param>
        /// <returns></returns>
        public static (string, string) GetMySqlUser(string cpuIp)
        {
            string userName = "";
            string passWord = "";
            //BFEBFBFF000906EA
            //BFEBFBFF000906EA
            Dictionary<string, Dictionary<string, string>> dic = new Dictionary<string, Dictionary<string, string>>()
            {
                {"BFEBFBFF000906EA",new Dictionary<string, string>()
                {
                    { "root","yk19991223"}
                } },
                {"BFEBFBFF000806EB",new Dictionary<string, string>()
                {
                    { "root","265422"}
                } }
            };

            foreach (var item in dic)
            {
                if (item.Key.Equals(cpuIp))
                {
                    //解析Value
                    foreach (var item1 in item.Value)
                    {
                        userName = item1.Key;
                        passWord = item1.Value;
                    }
                }
            }
            userName = string.IsNullOrEmpty(userName) ? SystemConstant.MySqlName : userName;
            passWord = string.IsNullOrEmpty(passWord) ? SystemConstant.MySqlPassWord : passWord;
            return (userName, passWord);
        }

        /// <summary>
        /// 请求对照表
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string UrlAnalysis(string url)
        {
            Dictionary<string, string> dic
                = new Dictionary<string, string>()
                {
                    {"OrderInfo","ProcessRequest" },
                    {"SpotCheckOk","SpotCheckOk" },
                    {"OrderEnd","OrderEnd" },
                    {"AdditionalOrder","AdditionalOrder" },
                    {"ISVGlue","ISVGlue" },
                    {"GetNgCode","GetNgCode" },
                    {"AndonTTS","AndonTTS" },
                    {"AndonDelete","AndonDelete" },
                    {"ReportingForWork","ReportingForWork" },
                    {"receiveReport","receiveReport" },
                    {"checkReport","checkReport" },
                };
            foreach (var item in dic)
            {
                if (url.Contains(item.Key))
                {
                    return item.Value;
                }
            }
            return "";
        }

        /// <summary>
        /// 线体编码与PlcName的映射
        /// </summary>
        /// <returns></returns>
        public static string GetTasksType(string lineName)
        {
            Dictionary<string, string> taskList = new Dictionary<string, string>()
            {
                { "218","front"},
                { "216","sub"},
            };
            return taskList.TryGetValue(lineName, out string plcName) ? plcName : "";
        }

        /// <summary>
        /// 根据年份获取标识
        /// </summary>
        /// <param name="year"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static string GetYear(int year)
        {
            // 定义一个年份到字母的映射
            var yearToLetterMap = new Dictionary<int, string>
            {
                { 2024, "R" },
                { 2025, "S" },
                { 2026, "T" },
                { 2027, "V" },
                { 2028, "W" },
                { 2029, "X" },
                { 2030, "Y" }
            };

            // 检查年份是否在映射中
            if (yearToLetterMap.TryGetValue(year, out string letter))
            {
                return letter;
            }

            // 如果年份未定义，返回一个默认值或抛出异常
            throw new ArgumentException($"未定义年份 {year} 的对应字母。");
        }

        /// <summary>
        /// 根据月份获取标识
        /// </summary>
        /// <param name="month"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static string GetMonth(int month)
        {
            // 检查输入是否为有效月份
            if (month < 1 || month > 12)
            {
                throw new ArgumentException("月份必须在 1 到 12 之间。");
            }

            // 根据月份返回对应的字符串
            if (month >= 1 && month <= 9)
            {
                return month.ToString(); // 1 到 9 返回数字字符串
            }

            switch (month)
            {
                case 10:
                    return "A"; // 十月对应 A
                case 11:
                    return "B"; // 十一月对应 B
                case 12:
                    return "C"; // 十二月对应 C
                default:
                    throw new ArgumentException("无效的月份。");
            }
        }

        /// <summary>
        /// 根据天获取标识
        /// </summary>
        /// <param name="day"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static string GetDay(int day)
        {
            // 检查输入是否为有效日期
            if (day < 1 || day > 31)
            {
                throw new ArgumentException("日期必须在 1 到 31 之间。");
            }

            // 1 到 9 返回数字字符串
            if (day >= 1 && day <= 9)
            {
                return day.ToString();
            }

            // 10 到 31 映射到字母，跳过 I、O、Q 和 U
            char[] letters = "ABCDEFGHJKLMNPRSTVWXYZ".ToCharArray(); // 排除 I, O, Q, U
            int index = day - 10; // 计算映射到字母数组的索引

            if (index < letters.Length)
            {
                return letters[index].ToString();
            }

            throw new ArgumentException($"日期 {day} 超出字母映射范围。");
        }

        /// <summary>
        /// 安灯故障对照表
        /// </summary>
        /// <param name="deviceId"></param>
        /// <param name="faultMessage"></param>
        /// <returns></returns>
        public static bool DeviceIdInAndon(string deviceId, string faultMessage)
        {
            Dictionary<string, string> dic = new Dictionary<string, string>()
            {
                { "",""},
                { "",""},
                { "",""},
                { "",""},
                { "",""},
            };

            if (dic.TryGetValue(deviceId, out string message).Equals(faultMessage))
                return true;
            return false;
        }

        /// <summary>
        /// 通过工序编号获取点焊机器人对应编号
        /// </summary>
        /// <param name="operaiton"></param>
        /// <returns></returns>
        public static List<string> GetRobotByOperation(string operaiton)
        {
            Dictionary<string, List<string>> dic = new Dictionary<string, List<string>>
            {
                { "L1",new List<string> { "52" } },
                { "L2",new List<string> { "53" } },
                { "L3",new List<string> { "54" } },
                { "L4",new List<string> { "52" } },
                { "L5",new List<string> { "53" } },
                { "L6",new List<string> { "54" } },
                { "L7",new List<string> { "55" } },
                { "L8",new List<string> { "55" } },
                { "L11",new List<string> { "57","58" } },
                { "L12",new List<string> { "57","58" } },
                { "L13",new List<string> { "59" } },
                { "L14",new List<string> { "60" } },
                { "R1",new List<string> { "63" } },
                { "R2",new List<string> { "64" } },
                { "R3",new List<string> { "63" } },
                { "R4",new List<string> { "64" } },
                { "R5",new List<string> { "66" } },
                { "R6",new List<string> { "66" } },
                { "R9",new List<string> { "67" } },
                { "R10",new List<string> { "68","69" } },
                { "R11",new List<string> { "68", "69" } },
                { "R12",new List<string> { "70" } },
                { "R13",new List<string> { "71" } },
                {"SC12-1",new List<string>{"36"}},
                {"SC12-2",new List<string>{"36"}},
                {"SC10-1",new List<string>{"37"}},
                {"SC10-3",new List<string>{"37"}},
                {"SC8-1",new List<string>{"38"}},
                {"SC8-2",new List<string>{"38"}},
                {"SC9-1",new List<string>{"38"}},
                {"SC11-1",new List<string>{"38"}},
            };
            if (dic.TryGetValue(operaiton, out var value))
            {
                return value;
            }
            else
            {
                return new List<string>();
            }
        }

        /// <summary>
        /// 根据线体号(任务号)与工序获取反馈Plc的偏移量
        /// </summary>
        /// <param name="lineName"></param>
        /// <param name="operation"></param>
        /// <returns></returns>
        public static (int, int) OperationGetOff(string plcName, string operation)
        {
            var dataDict = new Dictionary<string, Dictionary<string, Tuple<int, int>>>();

            // 添加数据
            dataDict["front"] = new Dictionary<string, Tuple<int, int>>
            {
                { "Op10Weld_A", new Tuple<int, int>(5, 0) },
                { "Op10Weld_B", new Tuple<int, int>(5, 1) },
                { "Op20FixedWeld", new Tuple<int, int>(5, 2) },
                { "Op30FixedGlue", new Tuple<int, int>(5, 3) },
                { "Op40Weld_A", new Tuple<int, int>(5, 4) },
                { "Op40Weld_B", new Tuple<int, int>(5, 5) },
                { "Op50FixedWeld", new Tuple<int, int>(5, 6) },
                { "Op60FixedGlue", new Tuple<int, int>(5, 7) },
                { "Op70Weld_A", new Tuple<int, int>(6, 0) },
                { "Op70Weld_B", new Tuple<int, int>(6, 1) },
                { "Op80FixedWeld", new Tuple<int, int>(6, 2) },
                { "Op90FixedGlue", new Tuple<int, int>(6, 3) },
                { "Op100Weld_A", new Tuple<int, int>(6, 4) },
                { "Op100Weld_B", new Tuple<int, int>(6, 5) },
                { "Op110FixedWeld", new Tuple<int, int>(6, 6) },
                { "Op120FixedStudWeld", new Tuple<int, int>(6, 7) },
                { "Op130StudWeld", new Tuple<int, int>(7, 0) },
                { "Op140Point", new Tuple<int, int>(7, 1) },
                { "Op150Vision_A", new Tuple<int, int>(7, 2) },
                { "Op150Vision_B", new Tuple<int, int>(7, 3) },
            };

            dataDict["sub"] = new Dictionary<string, Tuple<int, int>>
            {
                { "Op10Glue", new Tuple<int, int>(5, 0) },
                { "Op20Weld", new Tuple<int, int>(5, 1) },
                { "Op30Weld_A", new Tuple<int, int>(5, 2) },
                { "Op30Weld_B", new Tuple<int, int>(5, 3) },
                { "Op40Weld", new Tuple<int, int>(5, 4) },
                { "Op50Weld", new Tuple<int, int>(5, 5) },
                { "Op60Weld", new Tuple<int, int>(5, 6) },
                { "Op70Weld", new Tuple<int, int>(5, 7) },
            };

            if (dataDict.ContainsKey(plcName) && dataDict[plcName].ContainsKey(operation))
            {
                var result = dataDict[plcName][operation];
                return (result.Item1, result.Item2);
            }
            Tools.ProduceLogTextError(plcName + ":" + operation);

            return (10, 10);
        }

        /// <summary>
        /// 根据工厂下发工序号获取对应线体中存储的工序号
        /// </summary>
        /// <param name="operation"></param>
        /// <param name="MaterialCode"></param>
        /// <returns></returns>
        public static (string,bool) GetOperation(string operation, string MaterialCode)
        {
            // CQYQ-B04340004-01-RSW
            Dictionary<string, Dictionary<string, string>> dic = new Dictionary<string, Dictionary<string, string>>()
            {
                { "front",new Dictionary<string, string>{ 
                    { "CQYQ-C3404-02-RSW", "Op10Weld" }, 
                    { "CQYQ-C3404-05-RSW", "Op40Weld" } , 
                    { "CQYQ-C3404-08-RSW", "Op70Weld" } , 
                    { "CQYQ-C3404-11-RSW", "Op100Weld" } } },

                { "sub",new Dictionary<string, string>{ 
                    { "CQYQ-B04340008-01-GLU", "Op10Glue" },
                    { "CQYQ-B04340008-02-RSW", "Op20Weld" } ,
                    { "CQYQ-B04340007-01-RSW", "Op30Weld_A" }, 
                    { "CQYQ-B04340009-01-RSW", "Op30Weld_B" },
                    { "CQYQ-B04340009-02-RSW", "Op40Weld" },
                    { "CQYQ-B04340009-03-RSW", "Op50Weld" },
                    { "CQYQ-B04340009-04-RSW", "Op60Weld" },
                    { "CQYQ-B04340001-01-RSW", "Op70Weld" } } },
            };
            if (dic.TryGetValue(MaterialCode, out Dictionary<string, string> operationDic))
                if (operationDic.TryGetValue(operation, out string value))
                    return (value,true);
            return (operation,false);
        }

        /// <summary>
        /// 根据不同零件号补全自动工序
        /// </summary>
        /// <param name="processCodes"></param>
        /// <returns></returns>
        public static List<string> AddOperation(List<string> operations, List<string> processCodes, string plcName)
        {
            Dictionary<string, List<string>> dic = new Dictionary<string, List<string>>()
            {
                { "front",new List<string>
                          {
                              "Op20FixedWeld",
                              "Op30FixedGlue",
                              "Op50FixedWeld",
                              "Op60FixedGlue",
                              "Op80FixedWeld",
                              "Op90FixedGlue",
                              "Op110FixedWeld",
                              "Op120FixedStudWeld",
                              "Op130StudWeld",
                              "Op140Point",
                              "Op150Vision_A",
                              "Op150Vision_B",
                          } 
                }
            };

            if (dic.TryGetValue(plcName, out List<string> value))
            {
                operations.AddRange(value);
            }
            operations.AddRange(processCodes);
            return operations;
        }

        public static bool MapRobot(string robot)
        {
            List<string> robots = new List<string>()
            {
                "52",
                "53",
                "55",
                "66",
                "63",
                "64"
            };
            return robots.Contains(robot);
        }

        /// <summary>
        /// 根据plcName获取该Plc存在的最大工单数量
        /// </summary>
        /// <param name="plcName"></param>
        /// <returns></returns>
        public static int GetCount(string plcName)
        {
            Dictionary<string, int> dic = new Dictionary<string, int>()
            {
                {"front",1 },
                {"sub",4 },
            };
            if (dic.TryGetValue(plcName,out int value))
            {
                return value;
            }
            return 0;
        }

        /// <summary>
        /// 判断是否是下件工序
        /// </summary>
        /// <param name="plcName"></param>
        /// <param name="operationReal"></param>
        /// <returns></returns>
        public static bool GetLinePart(string plcName, string operationReal)
        {
            Dictionary<string, List<string>> dic = new Dictionary<string, List<string>>()
            {
                { "sub",new List<string>(){ "Op10Glue", "Op20Weld", "Op30Weld_A", "Op60Weld", "Op70Weld" } }
            };
            if (dic.TryGetValue(plcName, out List<string> value))
                return value.Contains(operationReal);
            return false;
        }

        /// <summary>
        /// 判断是否是了然视觉工序
        /// </summary>
        /// <param name="plcName"></param>
        /// <param name="operationReal"></param>
        /// <returns></returns>
        public static bool GetVisionOperation(string plcName, string operationReal)
        {
            Dictionary<string, string> dic = new Dictionary<string, string>()
            {
                { "front","Vision"}
            };
            if (dic.TryGetValue(plcName, out string operation))
            {
                if (operation.Contains(operationReal))
                    return true;
            }
            return false;
        }

        /// <summary>
        /// 获取工单下发索引
        /// </summary>
        /// <param name="materialCode"></param>
        /// <returns></returns>
        public static int GetOrderCount(string materialCode)
        {
            Dictionary<string, int> dic = new Dictionary<string, int>()
            {
                // front
                {"C34000004", 1},

                // sub
                {"B04340001", 1},
                {"B04340009", 2},
                {"B04340007", 3},
                {"B04340008", 4},
            };

            if (dic.TryGetValue(materialCode, out int count))
                return count;
            return 10;
        }
    }
}
